package chapters16;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by xinxuchu on 2020/1/31.
 * 生产者/消费者模式
 * 显示锁和显示条件实现
 *
 * 我们用wait/notify实现了生产者/消费者模式，
 * 我们提到了wait/notify的一个局限，它只能有一个条件等待队列，
 * 分析等待条件也很复杂。
 *
 * 在生产者/消费者模式中，其实有两个条件，
 * 一个与队列满有关，一个与队列空有关。
 *
 * 多个队列使用之前的wait和notify是不行的
 */
public class MyBlockingQueue<E> {
    private Queue<E> queue = null;
    private int limit;
    private Lock lock = new ReentrantLock();
    private Condition notfull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public MyBlockingQueue(int limit) {
        this.limit = limit;
        queue = new ArrayDeque<>(limit);
    }

    //生产者模式
    public void put(E e) throws InterruptedException{
        lock.lockInterruptibly();
        try {
            while (queue.size() == limit){
                notfull.await();
            }
            queue.add(e);
            notEmpty.signal();
        }finally {
            lock.unlock();
        }
    }

    //消费者模式
    public E take() throws InterruptedException{
        lock.lockInterruptibly();
        try {
            while (queue.isEmpty()){
                notEmpty.wait();
            }
            E e = queue.poll();
            notfull.signal();
            return e;
        }finally {
            lock.unlock();
        }
    }


}
